{
 "cells": [
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "## 1.导包",
   "id": "f4d1b841ba510ee6"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-11-07T02:00:14.675723Z",
     "start_time": "2024-11-07T02:00:11.923Z"
    }
   },
   "cell_type": "code",
   "source": [
    "import matplotlib.pyplot as plt\n",
    "import torch\n",
    "from matplotlib.font_manager import FontProperties\n",
    "from torchvision.datasets import MNIST\n",
    "from torch.utils.data import DataLoader\n",
    "from torchvision.transforms import transforms\n",
    "import matplotlib.pyplot as plt\n",
    "import matplotlib.font_manager as fm"
   ],
   "id": "33b71fa15f72d26a",
   "outputs": [],
   "execution_count": 1
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "## 2.导入MNIST数据",
   "id": "8749f8d23c4a5727"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-11-07T02:00:48.794863Z",
     "start_time": "2024-11-07T02:00:48.657272Z"
    }
   },
   "cell_type": "code",
   "source": [
    "mnist_train = MNIST('../data', train=True, transform=transforms.ToTensor(), download=True)\n",
    "mnist_test = MNIST('../data', train=False, transform=transforms.ToTensor(), download=True)\n",
    "len(mnist_train), len(mnist_test),type(mnist_train)"
   ],
   "id": "aefba4f2ed224366",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(60000, 10000, torchvision.datasets.mnist.MNIST)"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 3
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "## 3.小批量获取数据集",
   "id": "3c1dece85ebcb251"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-11-07T02:01:19.697171Z",
     "start_time": "2024-11-07T02:01:19.690483Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# dataset: 数据集 shuffle: 是否随机；batch_size: 批量获取数据的大小；num_workers: 使用的进程数\n",
    "train_loader = DataLoader(dataset=mnist_train, shuffle=True, batch_size=10, num_workers=4)\n",
    "test_loader = DataLoader(dataset=mnist_test, shuffle=False, batch_size=10, num_workers=4)\n"
   ],
   "id": "6f5d6412c3f60c5d",
   "outputs": [],
   "execution_count": 4
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "## 4.创建全链路层",
   "id": "af814c72daedeac"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-11-07T02:04:11.426011Z",
     "start_time": "2024-11-07T02:04:11.417284Z"
    }
   },
   "cell_type": "code",
   "source": [
    "import torch.nn as nn\n",
    "# 使用展平层来调整网络输入的形状，用于将输入张量展平成一维张量。这在卷积神经网络（CNN）中特别有用，因为卷积层通常会输出多维张量（例如，形状为 [batch_size, channels, height, width]），而在全连接层（也称为线性层）之前，通常需要将这些多维张量展平成一维张量。\n",
    "net = nn.Sequential(nn.Flatten(), nn.Linear(28*28, 10))\n",
    "type(net)"
   ],
   "id": "40282a5e2b34df27",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "torch.nn.modules.container.Sequential"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 5
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "## 5.初始化参数",
   "id": "38019a3fffccba25"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-11-07T02:10:51.757147Z",
     "start_time": "2024-11-07T02:10:51.749155Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# nn.Module.apply 是 PyTorch 中的一个方法，用于递归地对模块及其所有子模块应用一个函数。这个方法在初始化模型参数、自定义模块行为等方面非常有用。通过 apply 方法，你可以遍历整个模型的层次结构，并对每个模块或参数进行操作。\n",
    "def apply_test(m):\n",
    "    print(type(m))\n",
    "net.apply(apply_test)    "
   ],
   "id": "617e191937677013",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'torch.nn.modules.flatten.Flatten'>\n",
      "<class 'torch.nn.modules.linear.Linear'>\n",
      "<class 'torch.nn.modules.container.Sequential'>\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "Sequential(\n",
       "  (0): Flatten(start_dim=1, end_dim=-1)\n",
       "  (1): Linear(in_features=784, out_features=10, bias=True)\n",
       ")"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 7
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-11-07T04:53:41.784812Z",
     "start_time": "2024-11-07T04:53:41.779232Z"
    }
   },
   "cell_type": "code",
   "source": [
    "def init_weights(m):\n",
    "    if type(m) == nn.Linear:\n",
    "        nn.init.normal_(m.weight, std=0.01) # 以均值"
   ],
   "id": "38ee8f7c413b2c58",
   "outputs": [],
   "execution_count": 9
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "## 6.定义损失函数",
   "id": "cf261cdd0fdf6802"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-11-07T04:53:44.202575Z",
     "start_time": "2024-11-07T04:53:44.197665Z"
    }
   },
   "cell_type": "code",
   "source": "loss_fn = nn.CrossEntropyLoss(reduction=\"none\")",
   "id": "ccccf0abb5a83104",
   "outputs": [],
   "execution_count": 10
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "## 7.优化算法",
   "id": "3f6c413de20efd31"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-11-07T04:54:04.301619Z",
     "start_time": "2024-11-07T04:54:04.295856Z"
    }
   },
   "cell_type": "code",
   "source": "optimizer = torch.optim.SGD(net.parameters(), lr=0.1)",
   "id": "6335f67a1547ac",
   "outputs": [],
   "execution_count": 12
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "## 8.训练",
   "id": "4f2dfa0fc09ceefa"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-11-07T04:59:57.576553Z",
     "start_time": "2024-11-07T04:58:20.534913Z"
    }
   },
   "cell_type": "code",
   "source": [
    "num_epochs = 10 # 训练轮数\n",
    "for epoch in range(num_epochs):\n",
    "    for X,y in train_loader:\n",
    "        y_hat = net(X)\n",
    "        l = loss_fn(y_hat,y)\n",
    "        optimizer.zero_grad()\n",
    "        l.sum().backward() # 反向传播自动微分获取w和b的梯度\n",
    "        optimizer.step() # 用于更新模型的参数。这个方法根据计算出的梯度来调整模型参数，以最小化损失函数\n"
   ],
   "id": "d140e83ec41e58a4",
   "outputs": [],
   "execution_count": 18
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "## 10.预测",
   "id": "d3116bee9d48977e"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-11-07T05:02:09.803361Z",
     "start_time": "2024-11-07T05:02:09.684703Z"
    }
   },
   "cell_type": "code",
   "source": [
    "def get_labels(labels):\n",
    "    text_labels = [\"t-shirt(T恤)\", \"trouser(裤子)\", \"pullover(套衫)\", \"dress(连衣裙)\", \"coat(外套)\", \"sandal(凉鞋)\",\"shirt(衬衫)\", \"sneaker(运动鞋)\",\n",
    "                   \"bag(包)\", \"ankle boot(短靴)\"]\n",
    "    return [text_labels[int(label)] for label in labels ]\n",
    "for X,y in test_loader:\n",
    "    break;\n",
    "trues = get_labels(y)\n",
    "preds = get_labels(net(X).argmax(axis=1))\n",
    "print(trues)\n",
    "print(preds)"
   ],
   "id": "15da97a20e73f819",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['sneaker(运动鞋)', 'pullover(套衫)', 'trouser(裤子)', 't-shirt(T恤)', 'coat(外套)', 'trouser(裤子)', 'coat(外套)', 'ankle boot(短靴)', 'sandal(凉鞋)', 'ankle boot(短靴)']\n",
      "['sneaker(运动鞋)', 'pullover(套衫)', 'trouser(裤子)', 't-shirt(T恤)', 'coat(外套)', 'trouser(裤子)', 'coat(外套)', 'ankle boot(短靴)', 'shirt(衬衫)', 'ankle boot(短靴)']\n"
     ]
    }
   ],
   "execution_count": 19
  },
  {
   "metadata": {},
   "cell_type": "code",
   "outputs": [],
   "execution_count": null,
   "source": "",
   "id": "4ef83d45ec7567b7"
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
